package licode.unisop.single.user.application.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import licode.unisop.provider.conf.SiAssetState;
import licode.unisop.provider.info.UserGroupLookupIn;
import licode.unisop.provider.info.UserGroupSaveIn;
import licode.unisop.provider.vo.SiUserGroup;
import licode.unisop.realm.client.api.SiRealmService;
import licode.unisop.realm.client.dto.SiRealmDTO;
import licode.unisop.realm.client.info.SiPlatformAssignIn;
import licode.unisop.realm.client.info.SiRealmAttrRemoveIn;
import licode.unisop.realm.client.info.SiRealmGroupAttrRemoveIn;
import licode.unisop.single.user.application.entity.RealmAssetEntity;
import licode.unisop.single.user.application.gateway.RealmAssetDao;
import licode.unisop.single.user.application.gateway.RealmPlatformGrantDao;
import licode.unisop.single.user.domain.aggregate.entity.RealmsEntity;
import licode.unisop.single.user.domain.aggregate.repository.RealmsDao;
import licode.unisop.types.AuthConst;
import licode.unisop.types.util.IdGenUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * 实现领域操作
 *
 * @author licode
 */
@Service
public class SiRealmServiceDefault implements SiRealmService {
    @Resource
    private RealmsDao realmsDao;

    @Resource
    private RealmAssetDao realmAssetDao;

    @Resource
    private RealmPlatformGrantDao realmPlatformGrantDao;

    public void updateRealm(RealmsEntity realm, RealmsEntity existRealm) {
        realm.setId(existRealm.getId());
        if (existRealm.getProps() != null) {
            if (null == realm.getProps()) {
                realm.setProps(existRealm.getProps());
            } else {
                existRealm.getProps().forEach((key, val) -> {
                    if (!realm.getProps().containsKey(key)) {
                        realm.getProps().put(key, val);
                    }
                });
            }
        }

        realmsDao.update(realm);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class, timeout = 60)
    public void saveRealm(SiRealmDTO realm) {
        RealmsEntity entity = null;

        checkParams(realm);

        if (StrUtil.isNotBlank(realm.getId())) {
            entity = realmsDao.getWithId(realm.getId());
        }

        if (null != entity) {
            RealmsEntity existRealm = entity;
            entity = BeanUtil.copyProperties(realm, RealmsEntity.class);
            entity.setUpdateTime(LocalDateTime.now());
            updateRealm(entity, existRealm);
        } else {
            entity = BeanUtil.copyProperties(realm, RealmsEntity.class);

            entity.setId(IdGenUtil.buildRealmId());
            entity.setUpdateTime(LocalDateTime.now());
            entity.setCreateTime(LocalDateTime.now());

            realmsDao.add(entity);

            // 增加一条默认分组信息
            realmAssetDao.add(RealmAssetEntity.builder()
                    .id("default")
                    .type("USER_GROUP")
                    .subType("")
                    .rootId("default")
                    .classify("")
                    .parentId("")
                    .code("")
                    .ownerId(entity.getId())
                    .terminalCode("")
                    .name("默认")
                    .state(SiAssetState.AT_ACTIVATE)
                    .level(0)
                    .props(null)
                    .updateTime(LocalDateTime.now())
                    .createTime(LocalDateTime.now())
                    .build());
        }
    }

    @Override
    public void removeAttrOfRealm(SiRealmAttrRemoveIn req) {
        RealmsEntity realm = realmsDao.getWithId(req.getRealmId());
        if (null != realm && null != realm.getProps() && null != req.getProps()) {
            req.getProps().forEach(item -> realm.getProps().remove(item));
            realmsDao.update(realm);
        }
    }

    @Override
    public void removeAttrOfRealmGroup(SiRealmGroupAttrRemoveIn req) {
        SiUserGroup group = realmAssetDao.lookupUserGroup(UserGroupLookupIn.builder()
                .realmId(req.getRealmId())
                .groupId(req.getGroupId()).build());
        if (null != group && null != group.getProps() && null != req.getProps()) {
            req.getProps().forEach(item -> group.getProps().remove(item));
            realmAssetDao.saveUserGroup(UserGroupSaveIn.builder()
                    .realmId(req.getRealmId())
                    .group(group)
                    .build());
        }
    }

    @Override
    public void assignPlatform(SiPlatformAssignIn req) {
        realmPlatformGrantDao.assignPlatform(req);
    }

    @Override
    public void removePlatform(SiPlatformAssignIn req) {
        realmPlatformGrantDao.removePlatform(req);
    }


    private void checkParams(SiRealmDTO realm) {
        if (AuthConst.DEFAULT_ID.equals(realm.getId())) {
            realm.setState(SiAssetState.AT_ACTIVATE);
        }

        if (StrUtil.isBlank(realm.getRealmCode())) {
            realm.setRealmCode("");
        }

        if (StrUtil.isBlank(realm.getOrgName())) {
            realm.setOrgName("");
        }

        if (StrUtil.isBlank(realm.getOrgCode())) {
            realm.setOrgCode("");
        }

        if (StrUtil.isBlank(realm.getOrgContact())) {
            realm.setOrgContact("");
        }

        if (StrUtil.isBlank(realm.getUserUrl())) {
            realm.setUserUrl("");
        }

        if (StrUtil.isBlank(realm.getProviderId())) {
            realm.setProviderId("");
        }
    }
}
